/******************************************************************* IPCWindow.c Does open a simple window with some easy gadgets, does create a new process, is protected to launch not twice and does show all arguments even if they are given with a new command. *********************************************************************/ #define PARENT #include "/includes/Window.h" typedef struct _PassingData { ULONG a4; // to store a4 (module is a4 relative) struct Library *library; // to store a pointer to dopus5.library struct Library *module; // to store a pointer to this module IPCData *ipc; // to store our NEW handle struct Screen *screen; } PassingData; /********************************************************************/ // locale prototypes and variables ULONG __asm __saveds New_Proc_Startup( register __a0 IPCData *ipc, register __a1 PassingData *pd ); void __saveds New_Proc( void ); BOOL OpenDOpusWin( WindowHandle *wh ); // the same old function BOOL HandleWindow( WindowHandle *wh ); // the same old function extern IPCData *proc_ipc; // declared in modinit.c, because must be initialized to NULL on startup /********************************************************************/ // this is the same function like in DetachWindow. // it is the first special function we need... void OwnWindow( STRPTR args, struct Screen *screen ) { PassingData *pd; if( (pd = AllocMemH(mempool, sizeof(PassingData))) ) // allocate some memory { pd->screen = screen; // store the screen pointer if( !proc_ipc ) // only if the process is not already running { // now some special stuff, but everything is needed here... pd->a4 = getreg( REG_A4 ); pd->module = (struct Library *) getreg( REG_A6 ); pd->library = DOpusBase; // now we are ready to call IPC_Launch() IPC_Launch( 0, &proc_ipc, // pointer to pointer to the IPC of the new process, for storing... "ExampleWindow", // name of the new process (ULONG) New_Proc, // entrypoint of the new process 4096, // stack to use (ULONG) pd, // data to pass to the new process DOSBase ); // pointer to dos.library if( !proc_ipc ) // if detaching failed... { FreeMemH( pd ); return; } Delay( 10 ); // give a small time for startup... // not really needed } // now should our process running // since we use in the process not the arguments on startup to save // some work, we have to pass it now. IPC_Command( proc_ipc, // "address" (IPCData) of receiver NULL, // we use no commands here NULL, // also no flags args, // our data to pass to the new process NULL, // no other data (will be FreeVec'd) REPLY_NO_PORT ); // use normal DOpus IPC_Reply() later FreeMemH( pd ); } // ready... :) } // let's do now the second special function ULONG __asm __saveds New_Proc_Startup( register __a0 IPCData *ipc, register __a1 PassingData *pd ) { // you may use this function also to setup things for your // main process, but you should not call any IPC functions here ! // we do only the minimum required..., but you will get some small // warnings from your compiler. Just ignore them now - they does // not appear, if we would do here some more things... struct Library *DOpusBase; // fix A4 putreg( REG_A4, pd->a4 ); // store IPC pointer pd->ipc = ipc; // get dopus.library - one warning now DOpusBase = pd->library; // now may follow your initialization // if something fails and you must quit, you should do: // return FALSE; // increase our library counter, so we can not be flushed // do not forget to decrease it, if your detached process ends pd->module->lib_OpenCnt++; return TRUE; // all was successfully } void __saveds New_Proc( void ) { // this is now just the same like until now our OwnWindow() function WindowHandle *wh; PassingData *pd; IPCData *ipc; IPCMessage *ipcmsg; struct Library *DOpusBase; struct Library *module; // but we must do some additional things // get dopus library if( !(DOpusBase = (struct Library *) FindName(&((struct ExecBase *)*((ULONG *)4))->LibList, "dopus5.library")) ) return; // do startup ipc = IPC_ProcStartup( (ULONG *) &pd, New_Proc_Startup ); // fix A4 so we can access global data in the module (eg library bases) putreg( REG_A4, pd->a4 ); // we must store this pointer too module = pd->module; // something failed until now ? if( !ipc ) { if( pd ) { IPC_Free( pd->ipc ); // possible it has a value here FreeMemH( pd ); // free our memory } return; } if( (wh = AllocMemH(mempool, sizeof(WindowHandle))) ) // allocate some memory { if( OpenDOpusWin(wh) ) // open the window { // before we have set on this place the value of our // textgadget, but now we have not the arguments. So // we wait to set the value until the command arrives. while( TRUE ) { // I use here Wait(), so it is easier with the changes wh->signals = Wait( 1 << proc_ipc->command_port->mp_SigBit | // wait for IPC messages 1 << wh->win->UserPort->mp_SigBit ); // wait for window events if( wh->signals & 1 << wh->win->UserPort->mp_SigBit ) if( HandleWindow(wh) ) break; // does end the while loop if( wh->signals & 1 << proc_ipc->command_port->mp_SigBit ) // if we have got an IPC message { while( (ipcmsg = (IPCMessage *) GetMsg(proc_ipc->command_port)) ) { // we copy now the arguments into the text gadget // if we have supplied some..., else it will be cleared // I do not cut here the last signs... SetGadgetValue( wh->olist, GADGET_ID_TEXT, (ULONG) ipcmsg->data ); IPC_Reply( ipcmsg ); // do not use ReplyMsg() or something else ! } } } CloseConfigWindow( wh->win ); } FreeMemH( wh ); // free our memory } // decrease our Library access counter, since we have increased it before --module->lib_OpenCnt; // since we are here a detached process, we must do some other cleanup too IPC_Free( proc_ipc ); proc_ipc = NULL; // do not forget this... } /********************************************************************/ // This function does open our window. We could have done this in the // function OwnWindow() too, but we need this function later again. BOOL OpenDOpusWin( WindowHandle *wh ) { NewConfigWindow ncfgwin; // we need a NewConfigWindow structure too // of couse you could also allocate it with // AllocMemH()... // and have to fill it ncfgwin.nw_Parent = wh->screen; // open on this screen // getting a localized title... ncfgwin.nw_Title = DOpusGetString( locale, MSG_WINDOW_TITLE ); ncfgwin.nw_Dims = &cfgwin; // a pointer to the ConfigWin structure ncfgwin.nw_Locale = locale; // the module locale pointer (from modinit.c) ncfgwin.nw_Port = NULL; // we doesn't supply a port ncfgwin.nw_Font = NULL; // just taking the screen font ncfgwin.nw_Flags = WINDOW_REQ_FILL | // fill with stripple pattern WINDOW_AUTO_KEYS | // handle keys automatic WINDOW_SCREEN_PARENT; // nw_Parent points to a screen if( (wh->win = OpenConfigWindow(&ncfgwin)) ) // open the window { if( (wh->olist = AddObjectList(wh->win, odef)) ) // add the gadgets return TRUE; CloseConfigWindow( wh->win ); // in error case do not forget :-) } return FALSE; } /********************************************************************/ // we does only close the window, if the closegadget was pressed // if you want to close it within a gadget, you must only in the // right case set "stop" to TRUE BOOL HandleWindow( WindowHandle *wh ) { BOOL stop = FALSE; ULONG value; while( !stop && (wh->imsg = GetWindowMsg(wh->win->UserPort)) ) { switch( wh->imsg->Class ) // let's handle the IDCMP { case IDCMP_GADGETUP: switch( GET_ID(wh->imsg) ) { case GADGET_ID_CYCLE: // we copy simply the same text to the text gadget value = GetGadgetValue( wh->olist, GADGET_ID_CYCLE ) + MSG_CLICK_ME; SetGadgetValue( wh->olist, GADGET_ID_TEXT, (ULONG) DOpusGetString(locale, value) ); break; case GADGET_ID_OKAY: // doing a message SetGadgetValue( wh->olist, GADGET_ID_TEXT, (ULONG) DOpusGetString(locale, MSG_OKAY_DONE) ); break; case GADGET_ID_CANCEL: SetGadgetValue( wh->olist, GADGET_ID_TEXT, (ULONG) DOpusGetString(locale, MSG_CANCEL_DONE) ); break; } break; case IDCMP_CLOSEWINDOW: // we can not simply return here, the IntuiMessage must replied first stop = TRUE; break; } ReplyWindowMsg( wh->imsg ); // remember: You should not use any other routines // to get/reply the messages of this window than // GetWindowMsg() and ReplyWindowMsg() !! } return stop; }